Monotonic array [Two Pass,One Pass]

Time: O(N); Space: O(1); easy

An array is monotonic if it is either monotone increasing or monotone decreasing.

An array A is monotone increasing if for all i <= j, A[i] <= A[j]. An array A is monotone decreasing if for all i <= j, A[i] >= A[j].

Return true if and only if the given array A is monotonic.

Example 1:

Input: A = [1,2,2,3]

Output: True

Example 2:

Input: A = [6,5,4,4]

Output: True

Example 3:

Input: A = [1,3,2]

Output: False

Example 4:

Input: A = [1,2,4,5]

Output: True

Example 5:

Input: A = [1,1,1]

Output: True

Note:

  • 1 <= A.length <= 50000

  • -100000 <= A[i] <= 100000

1. Two Pass

Intuition An array is monotonic if it is monotone increasing, or monotone decreasing. Since a <= b and b <= c implies a <= c, we only need to check adjacent elements to determine if the array is monotone increasing (or decreasing, respectively). We can check each of these properties in one pass.

Algorithm To check whether an array A is monotone increasing, we’ll check A[i] <= A[i+1] for all i. The check for monotone decreasing is similar.

[1]:
class Solution1(object):
    """
    Two Pass
    """
    def isMonotonic(self, A):
        """
        :type A: List[int]
        :rtype: bool
        """
        return (all(A[i] <= A[i+1] for i in range(len(A) - 1)) or
                all(A[i] >= A[i+1] for i in range(len(A) - 1)))
[2]:
s = Solution1()
A = [1,2,2,3]
assert s.isMonotonic(A) == True
A = [6,5,4,4]
assert s.isMonotonic(A) == True
A = [1,3,2]
assert s.isMonotonic(A) == False
A = [1,2,4,5]
assert s.isMonotonic(A) == True
A = [1,1,1]
assert s.isMonotonic(A) == True

2. One Pass

Intuition To perform this check in one pass, we want to handle a stream of comparisons from {-1, 0, 1}, corresponding to <, ==, or >. For example, with the array [1, 2, 2, 3, 0], we will see the stream (-1, 0, -1, 1).

Algorithm Keep track of store, equal to the first non-zero comparison seen (if it exists.) If we see the opposite comparison, the answer is False. Otherwise, every comparison was (necessarily) in the set {-1, 0}, or every comparison was in the set {0, 1}, and therefore the array is monotonic.

[3]:
class Solution2(object):
    """
    One Pass
    """
    def cmp(self, a, b):
        if a < b:
            return -1
        elif a > b:
            return 1
        else:
            return 0

    def isMonotonic(self, A):
        """
        :type A: List[int]
        :rtype: bool
        """
        store = 0
        for i in range(len(A) - 1):
            c = self.cmp(A[i], A[i+1])
            if c:
                if c != store != 0:
                    return False
                store = c
        return True
[4]:
s = Solution2()
A = [1,2,2,3]
assert s.isMonotonic(A) == True
A = [6,5,4,4]
assert s.isMonotonic(A) == True
A = [1,3,2]
assert s.isMonotonic(A) == False
A = [1,2,4,5]
assert s.isMonotonic(A) == True
A = [1,1,1]
assert s.isMonotonic(A) == True
[5]:
class Solution3(object):
    def isMonotonic(self, A):
        """
        :type A: List[int]
        :rtype: bool
        """
        inc, dec = False, False
        for i in range(len(A) - 1):
            if A[i] < A[i + 1]:
                inc = True
            elif A[i] > A[i + 1]:
                dec = True
        return not inc or not dec
[6]:
s = Solution3()
A = [1,2,2,3]
assert s.isMonotonic(A) == True
A = [6,5,4,4]
assert s.isMonotonic(A) == True
A = [1,3,2]
assert s.isMonotonic(A) == False
A = [1,2,4,5]
assert s.isMonotonic(A) == True
A = [1,1,1]
assert s.isMonotonic(A) == True